/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sunrise.utility;

import com.github.dvdme.ForecastIOLib.FIODataPoint;
import com.sunrise.bean.EmailSessionBean;
import com.sunrise.boundary.EventManager;
import com.sunrise.boundary.WeatherAlertManager;
import com.sunrise.boundary.WeatherManager;
import com.sunrise.entity.Event;
import com.sunrise.entity.InvitationRequest;
import com.sunrise.entity.User;
import com.sunrise.entity.WeatherAlert;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;

/**
 *
 * @author Andrea
 */
@Singleton
public class WeatherChecker {

    public final long _SECONDSONEDAY = 86400;
    public final long _SECONDSTHREEDAYS = 259200;
    public final long _SECONDSSEVENDAYS = 640800;

    private EmailSessionBean emailSessionBean = new EmailSessionBean();

    @EJB
    private EventManager eventManager;

    @EJB
    private WeatherManager weatherManager;

    @EJB
    private WeatherAlertManager weatherAlertManager;

    @PostConstruct
    private void constructed() {
    }

    @Schedule(minute="*/30", hour="*")
//    @Schedule(second = "*/50", minute = "*", hour = "*")
    public void checkWeather() {

        System.out.print("weather checker started....");

        List<Event> outdoorEvents = eventManager.findOutdoorEvents();

        Date today = new Date();

        for (Event outdoorEvent : outdoorEvents) {
            long dateDiff = dateDiffSeconds(today, outdoorEvent.getStartDate());

            boolean shouldBeCheckedThreeDays = _SECONDSONEDAY < dateDiff && dateDiff < _SECONDSTHREEDAYS && !outdoorEvent.isCheckedThreeDays();
            boolean shouldBeCheckedOneDay = 0 < dateDiff && dateDiff < _SECONDSONEDAY && !outdoorEvent.isCheckedOneDay();

            if (shouldBeCheckedThreeDays || shouldBeCheckedOneDay) {

                String latitude = outdoorEvent.getLocation().getLatitude();
                String longitude = outdoorEvent.getLocation().getLongitude();

                if (outdoorEvent.getStartDate() != null) {

                    List<FIODataPoint> dailyForecasts = weatherManager.getWeatherForLocation(latitude, longitude);
                    if (dailyForecasts.isEmpty()) {
                        break;
                    }

                    boolean badWeather = weatherManager.badWeatherForLocationAndDate(dailyForecasts, outdoorEvent.getStartDate());

                    if (badWeather) {
                        System.out.println("creating weather alerts for event " + outdoorEvent);
                        manageWeatherAlertsAndEmails(outdoorEvent, dailyForecasts);
                    }
                }

                boolean eventModified = false;
                if (shouldBeCheckedThreeDays) {

                    // in the case _SECONDSONEDAY < dateDiff && dateDiff < _SECONDSTHREEDAYS 
                    // && !outdoorEvent.isCheckedThreeDays() && outdoorEvent.isCheckedOneDay() 
                    // and therefore we correct isCheckedOneDay() because was an error
                    if (outdoorEvent.isCheckedOneDay()) {
                        outdoorEvent.setCheckedOneDay(false);
                    }

                    outdoorEvent.setCheckedThreeDays(true);
                    eventModified = true;
                } else if (shouldBeCheckedOneDay) {
                    outdoorEvent.setCheckedOneDay(true);
                    eventModified = true;
                }

                if (eventModified) {
                    eventManager.update(outdoorEvent);
                }
            }
        }
    }

    public void manageWeatherAlertsAndEmails(Event outdoorEvent, List<FIODataPoint> dailyForecasts) {
        Date today = new Date();
        long dateDiff = dateDiffSeconds(today, outdoorEvent.getStartDate());
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        FIODataPoint suggestedDataPoint = weatherManager.findSuggestedDataPoint(dailyForecasts, outdoorEvent.getStartDate());

        String suggestion = "";
        Date suggestedDate = null;

        if (suggestedDataPoint != null) {
            suggestedDate = weatherManager.dateStringForDay(suggestedDataPoint);
            suggestion = dateFormat.format(suggestedDate);
        }

        if (outdoorEvent.getCalendar().getOwner().isEmailEnabled()) {
            emailSessionBean.sendEmail(outdoorEvent.getCalendar().getOwner().getEmail(), "ALERT BAD WEATHER", "Bad weather forecasted\nEvent: " + outdoorEvent.getTitle() + "\nDate: " + outdoorEvent.getStartDate() + "\nSuggested alternative date: " + suggestion);
        }

        WeatherAlert weatherAlert = new WeatherAlert(outdoorEvent.getCalendar().getOwner(), outdoorEvent, suggestedDate);
        weatherAlertManager.save(weatherAlert);

        if (_SECONDSONEDAY < dateDiff && dateDiff < _SECONDSTHREEDAYS) {

        } else if (0 < dateDiff && dateDiff < _SECONDSONEDAY) {
            for (InvitationRequest invitationRequest : outdoorEvent.getInvitationRequests()) {
                weatherAlert = new WeatherAlert(invitationRequest.getRecipient(), outdoorEvent, null);
                weatherAlertManager.save(weatherAlert);
                if (invitationRequest.getRecipient().isEmailEnabled()) {
                    emailSessionBean.sendEmail(invitationRequest.getRecipient().getEmail(), "ALERT BAD WEATHER", "Bad weather forecasted\nEvent: " + outdoorEvent.getTitle() + "\nDate: " + outdoorEvent.getStartDate());
                }
            }
        }
    }

    public long dateDiffSeconds(Date lowerDate, Date higherDate) {
        if (higherDate != null && lowerDate != null) {
            long higherTime = higherDate.getTime();
            long lowerTime = lowerDate.getTime();
            long diffTime = higherTime - lowerTime;
            return diffTime / (1000);
        } else {
            return Long.MIN_VALUE;
        }
    }

}
